package com.ruoyi.framework.web.service;

import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.MoonUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.utils.HttpClientUtil;
import com.ruoyi.common.utils.HttpClientUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.wx.WxMiniAppLoginResponseDO;
import com.ruoyi.moon.service.IMoonUserService;
import com.ruoyi.system.service.ISysConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.google.gson.Gson;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;
import java.util.Base64;

@Component
public class WechatService {

    @Autowired
    private IMoonUserService moonUserService;
    @Autowired
    private TokenService tokenService;
    //微信小程序appId
    @Value("${wx.minApp.appId}")
    private String appId;
    @Autowired
    private ISysConfigService configService;
    //微信小程序密钥
    @Value("${wx.minApp.appSecret}")
    private String appSecret;
    private static final String REQUEST_URL = "https://api.weixin.qq.com/sns/jscode2session";
    private static final String GRANT_TYPE = "authorization_code";

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public AjaxResult getUserInfoMap(WxMiniAppLoginResponseDO loginRequest) throws Exception {
        logger.info("loginRequest-{}",loginRequest);
        if(StringUtils.isEmpty(loginRequest.getEncryptedData())){
            return AjaxResult.error("登录失败");
        }
        JSONObject sessionKeyOpenId = getSessionKeyOrOpenId(loginRequest.getCode());
        logger.info("sessionKeyOpenId-{}",sessionKeyOpenId);
        Assert.isTrue(sessionKeyOpenId != null, "sessionKeyOpenId为空");
        // 获取openId && sessionKey
        String openId = sessionKeyOpenId.getString("openid");
        Assert.isTrue(openId != null, "openId为空");
//        loginRequestngch.setOpenId(openId);
        String sessionKey = sessionKeyOpenId.getString("session_key");
        AjaxResult ajax = AjaxResult.success();
        String accToken = getAccToken();
        LoginUser loginUser = new LoginUser();
        JSONObject encryptedData = getEncryptedData(loginRequest.getEncryptedData(), sessionKey, loginRequest.getIv());
        logger.info("data-{}",encryptedData);
        MoonUser userAuthInfoDO = buildWechatUserAuthInfoDO(loginRequest,accToken);
        if(StringUtils.isEmpty(userAuthInfoDO.getNickName())){
            String lastFourDigits = userAuthInfoDO.getPhoneNumber().substring(userAuthInfoDO.getPhoneNumber().length() - 4);
            userAuthInfoDO.setNickName("昵称_" + lastFourDigits);
//            userAuthInfoDO.setNickName("微信用户");
        }
        MoonUser user = moonUserService.getUserByPhone(userAuthInfoDO.getPhoneNumber());
        if(null == user){
            userAuthInfoDO.setPassword(SecurityUtils.encryptPassword(configService.selectConfigByKey("sys.user.initPassword")));
            userAuthInfoDO.setChannel("wechat");
            userAuthInfoDO.setImgUrl("/profile/upload/2025/01/09/yxTPvORYQ6Lp9ae74c3620f8f67ef5dd3b58f5d156a4_20250109181729A001.jpg");
            userAuthInfoDO.setOpenId(openId);
            userAuthInfoDO.setCreateTime(new Date());
            moonUserService.insertMoonUser(userAuthInfoDO);
            loginUser.setMoonUser(userAuthInfoDO);
            loginUser.setUserId(userAuthInfoDO.getId());
//            ajax.put("wechatUser",userAuthInfoDO);
        }else{
            if(UserStatus.DISABLE.getCode().equals(user.getDelFlag())){
                return AjaxResult.error("该账号已停封");
            }
            if (StringUtils.isEmpty(user.getOpenId())) {
                user.setOpenId(openId);
                moonUserService.updateMoonUser(user);
            }
            loginUser.setMoonUser(user);
            loginUser.setUserId(user.getId());
//            ajax.put("wechatUser",wechatUser);
        }
        String token = tokenService.createToken(loginUser);
        ajax.put(Constants.TOKEN,token);
        return ajax;
    }

    public String getAccToken() throws Exception {
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
        JSONObject token = JSON.parseObject(HttpClientUtil.get(tokenUrl));
        return token.getString("access_token");
    }

    private JSONObject getSessionKeyOrOpenId(String code) throws Exception {
//        Map<String, String> requestUrlParam = new HashMap<>();
//        requestUrlParam.put("appid", appId);
//        requestUrlParam.put("secret", appSecret);
//        // 小程序端返回的code
//        requestUrlParam.put("js_code", code);
//        requestUrlParam.put("grant_type", GRANT_TYPE);
//        // 发送post请求读取调用微信接口获取openid用户唯一标识
//        String result = HttpClientUtils.doPost(REQUEST_URL, requestUrlParam);
        //微信小程序获取openId请求地址
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}", appId).replace("{1}", appSecret).replace("{2}", code);
        String result = HttpUtil.get(replaceUrl);
        return JSON.parseObject(result);
    }
    public MoonUser buildWechatUserAuthInfoDO(WxMiniAppLoginResponseDO loginRequest,String token) throws Exception {

        MoonUser wechatUserDO = new MoonUser();
        String phoneNumber = getPhoneNumber(loginRequest,token);
        wechatUserDO.setPhoneNumber(phoneNumber);
        wechatUserDO.setNickName(loginRequest.getNickName());
        wechatUserDO.setImgUrl(loginRequest.getHeadimgUrl());
        // 解密加密信息，获取unionID
//        if (loginRequest.getEncryptedData() != null){
//            JSONObject encryptedData = getEncryptedData(loginRequest.getEncryptedData(), sessionKey, loginRequest.getIv());
//        }
        return wechatUserDO;
    }
    public String getPhoneNumber(WxMiniAppLoginResponseDO loginRequest,String token) throws Exception {
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + token;
        //封装请求体
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("code", loginRequest.getPhoneCode());

        //封装请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, String>> httpEntity = new HttpEntity<>(paramMap,headers);
        //通过RestTemplate发送请求，获取到用户手机号码
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Object> response = restTemplate.postForEntity(url, httpEntity, Object.class);
        Object body = response.getBody();
        Gson gson = new Gson();
        String json = gson.toJson(body);
        JSONObject jsonObject = JSONObject.parseObject(json);
        if(jsonObject.getString("errmsg").equals("ok")){
            JSONObject jsonObject2 = JSONObject.parseObject(jsonObject.getString("phone_info"));
            String purePhoneNumber = jsonObject2.getString("purePhoneNumber");
            return purePhoneNumber;
        }
        return null;
    }
    private JSONObject getEncryptedData(String encryptedData, String sessionkey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64.getDecoder().decode(encryptedData);

        // 加密秘钥
        byte[] keyByte = Base64.getDecoder().decode(sessionkey);
        // 偏移量
        byte[] ivByte = Base64.getDecoder().decode(iv);
        try {
            // 如果密钥不足16位，那么就补足.这个if中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + 1;
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            logger.error("解密加密信息报错", e.getMessage());
        }
        return null;
    }
}
